package com.apobates.forum.grief.function;

import org.apache.commons.lang3.tuple.Pair;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * 将递进的语句改为并行的
 * 普通:
 * 	String category = "approve";
 * 	Map<String, Object> objectMap = bzBusService.verifyCurrentUserAllowApprove(token);
 * 	if (objectMap.isEmpty()) {
 * 		objectMap = bzBusService.verifyCurrentUserAllowRevert(token);
 * 		if(!objectMap.isEmpty()) {
 * 			category = "revert";
 *      }else {
 * 			objectMap = bzBusService.verifyCurrentUserAllowAddApply(token);
 * 			if (!objectMap.isEmpty()) {
 * 				category = "apply";
 *          }
 *      }
 *  }
 * API:
 * 	Predicate<Map> pc = (pcMap)->null!=pcMap && !pcMap.isEmpty();
 * 	Pair<Map, String> mapStringPair = EffectivePairResult.<Map, String>of(pc)
 * 					.thenCase(() -> bzBusService.verifyCurrentUserAllowApprove(token), "approve")
 * 					.thenCase(() -> bzBusService.verifyCurrentUserAllowRevert(token), "revert")
 * 					.thenCase(() -> bzBusService.verifyCurrentUserAllowAddApply(token), "apply")
 * 					.get(Collections.emptyMap(), "-");
 * @param <T>
 * @param <U>
 * @author xiaofanku@live.cn
 * @since 20210901
 */
public class EffectivePairResult<T,U> {
    private final Predicate<T> condition;
    private final T data;
    private final U other;

    /**
     *
     * @param condition 递进的判断条件
     * @param data 结果1
     * @param other 结果2
     */
    private EffectivePairResult(Predicate<T> condition, T data, U other) {
        this.condition = condition;
        this.data = data;
        this.other = other;
    }

    private T getData() {
        return data;
    }

    private U getOther() {
        return other;
    }

    /**
     * 结果1是否有效.判断是否继续下一步的标记
     * @return
     */
    private boolean isEffective(){
        return null != getData();
    }

    /**
     * 设置递进的条件
     * @param condition 使用结果1作为谓词函数的输入项
     * @param <T>
     * @param <U>
     * @return
     */
    public static <T,U> EffectivePairResult<T,U> of(Predicate<T> condition){
        return new EffectivePairResult<>(condition, null, null);
    }

    /**
     * 设置递进的结果
     * @param source 结果1的计算函数
     * @param otherVal 结果2的值
     * @return
     */
    public EffectivePairResult<T,U> thenCase(Supplier<T> source, U otherVal){
        try {
            if (!isEffective() && condition.test(source.get())) {
                return new EffectivePairResult<>(condition, source.get(), otherVal);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return this;
    }
    /**
     * 合并结果
     * @param source 结果1的计算函数
     * @param collector 结果1的合并器
     * @param otherVal 结果2的值
     * @param otherCollector 结果2的合并器
     * @return
     */
    public EffectivePairResult<T,U> thenCollect(Supplier<T> source,
                                              EffectiveResultCollector<T> collector,
                                              U otherVal,
                                              EffectiveResultCollector<U> otherCollector){
        try {
            if (condition.test(source.get())) {
                //使用哪个值
                //新值?旧值?合并(集合|字符串)
                T currentData = null;
                if(!isEffective()){
                    currentData = source.get();
                }else {
                    currentData = collector.map(getData(), source.get());
                }

                U currentOther = null;
                if(null==getOther()){
                    currentOther = otherVal;
                }else {
                    currentOther = otherCollector.map(getOther(), otherVal);
                }
                return new EffectivePairResult<>(condition, currentData, currentOther);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return this;
    }

    /**
     * 返回结果
     * @param defaultData 结果1的默认值
     * @param defaultOther 结果2的默认值
     * @return Pair.left=结果1, Pair.right=结果2
     */
    public Pair<T,U> get(T defaultData, U defaultOther){
        return isEffective()?Pair.of(getData(), getOther()):Pair.of(defaultData, defaultOther);
    }

    /**
     * 返回结果
     * @return 若值不可用时left,right的值是null
     */
    public Pair<T,U> get(){
        return isEffective()?Pair.of(getData(), getOther()):Pair.of(null, null);
    }

    /**
     * 测试示例
     * @param args
     */
    public static void main(String[] args) {
        //测试:thenCase
        Predicate<Long> pc = (pcNum)->null!=pcNum && pcNum.compareTo(0L) ==1;
        Pair<Long, String> longStringPair = EffectivePairResult.<Long, String>of(pc)
                .thenCase(()->null, "等于null")
                .thenCase(() -> 2L, "大于0")
                .thenCase(() -> -1L, "小于0")
                .get(0L, "等于0");
        System.out.println("Long="+longStringPair.getLeft().toString()+",String="+longStringPair.getRight());
        System.out.println("------------------------------------");
        //测试:thenCollect
        Predicate<Map<String,String>> mc = (map)->null!=map && !map.isEmpty();
        Map<String,String> t1 = new HashMap<>();
        t1.put("age", "11");
        t1.put("name", "xiaofanku");
        Map<String,String> t2 = new HashMap<>();
        t2.put("age", "12");
        t2.put("name", "zhang");
        EffectiveResultCollector<Map<String,String>> mrc = (oldM,newM)->newM;
        EffectiveResultCollector<String> oth = (oldOTH,newOTH)->oldOTH.concat(","+newOTH);
        Pair<Map<String, String>, String> pair = EffectivePairResult.<Map<String, String>, String>of(mc)
                .thenCollect(() -> null, mrc, "-", oth)
                .thenCollect(() -> t1, mrc, "t1", oth)
                .thenCollect(() -> t2, mrc, "t2", oth)
                .get();
        Map<String, String> map = pair.getLeft();
        String right = pair.getRight();
        map.entrySet().stream().forEach(entry-> System.out.println("key="+entry.getKey()+",val="+entry.getValue()));
        System.out.println(right);
    }
}
